<?php
namespace App;
class SSH2
{
    /**
     * @var $host [远程主机ip或域名 host]
     */
    protected $host;
    /**
     * @var $port [端口 port]
     */
    protected $port;
    /**
     * @var $name [用户名 username]
     */
    protected $username;
    /**
     * @var $pwd [密码 password]
     */
    protected $pwd;
    /**
     * @var Resource [连接服务器资源]
     */
    protected $conn;
    /**
     * @var Resource [返回得资源数据流]
     */
    protected $stream;
    /**
     * @var Resource [返回得资源错误信息]
     */
    protected $error;
    /**
     * SSH2 constructor.
     * @throws \Exception
     */
    public function __construct()
    {
        if(!extension_loaded("ssh2")){
            throw new \Exception("请安装ssh2扩展！");
        }
    }
    /**
     * @param string $host
     * @return SSH2
     * @throws \Exception
     */
    public function setHost(string $host): self
    {
        $result = preg_match("/\w.*\.([a-z0-9].+\.{1,})[a-zA-Z]{1,6}$/", $host);
        if(!$result && !filter_var($host,FILTER_VALIDATE_IP,FILTER_FLAG_IPV4))
            throw new \Exception("host is illegal");
        $this->host = $host;
        return $this;
    }
    /**
     * @param int $port
     * @return SSH2
     * @throws \Exception
     */
    public function setPort(int $port): self
    {
        if($port > 65535 || $port <= 0)
            throw new \Exception("port value should between 1 and 65535");
        $this->port = $port;
        return $this;
    }
    /**
     * @param string $username
     * @return SSH2
     */
    public function setUsername(string $username): self
    {
        $this->username = $username;
        return $this;
    }
    /**
     * @param string $password
     * @return SSH2
     */
    public function setPassword(string $password): self
    {
        $this->pwd = $password;
        return $this;
    }
    /**
     * @param string $username
     * @param string $pwd
     * @param string $host
     * @param int $port
     * @return SSH2
     * @throws \Exception
     */
    public function connect(string $username = '', string $pwd = '', string $host = '', int $port = 0): self
    {
        if(!empty($username) ) $this->setUsername($username);
        if(!empty($pwd)) $this->setPassword($pwd);
        if(!empty($host) ) $this->setHost($host);
        if(!empty($port)) $this->setPort($port);
        $this->conn = ssh2_connect($this->host, $this->port);
        if(!$this->conn) throw new \Exception('connection to remote server failed!');
        $result = ssh2_auth_password($this->conn, $this->username, $this->pwd);
        if(!$result) throw new \Exception("username or password is illegal!");
        return $this;
    }
    /**
     * @param string $command
     * @param string $conn
     * @return SSH2
     */
    public function exec(string $command,$conn = ''): self
    {
        if(!empty($conn)) $this->conn = $conn;
        $this->stream = ssh2_exec($this->conn, $command);
        return $this;
    }
    /**
     * 获取交互式shell
     * @param string $conn
     * @return $this
     */
    public function shell($conn = '')
    {
        if(!empty($conn)) $this->conn = $conn;
        $this->stream = ssh2_shell($this->conn, 'xterm');
        return $this;
    }
    /**
     * 执行交互式命令
     * @param array $commands
     * @return $this
     */
    public function execInteractive(array $commands)
    {
        foreach ($commands as $item) {
            fwrite($this->stream, $item . PHP_EOL);
        }
        return $this;
    }
    /**
     * 获取最终结果
     * @return bool|string
     * @throws \Exception
     */
    public function get()
    {
        stream_set_timeout($this->stream, 15);
        stream_set_blocking($this->stream,true);
        $err = stream_get_contents(ssh2_fetch_stream($this->stream, SSH2_STREAM_STDERR));
        $result='';
        if( !empty($err)) $result = 'Error：' . $err;
        else {
//            $result = stream_get_contents($this->stream);
            while ($o = fgets($this->stream)) {
                $result .= $o ;
            }
        }
        return $result;
    }
    /**
     * @return Resource
     */
    public function getConnect()
    {
        return $this->conn;
    }
    /**
     * @param $name
     * @param $value
     * @return SSH2
     */
    public function __set($name, $value): self
    {
        if(property_exists($this, $name))
        $this->{$name} = $value;
        return $this;
    }
    /**
     * @param $name
     * @return mixed
     * @throws \Exception
     */
    public function __get($name)
    {
        if(property_exists($this, $name))
            return $this->{$name};
        else
            throw new \Exception("property does not exist!");
    }

    public function run_send($infile,$remoteFile,$conn=''){
        if(!empty($conn)) $this->conn = $conn;
        if ($this->conn)
        {
            if(ssh2_scp_send($this->conn, $infile, $remoteFile, 0644))
                return true;
            else
                return false;
        }else{
            return false;
        }
    }
}
